import {
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "./types";
import qs from "qs"; //只能在node中使用，不能在es6中使用，需要安装@rollup/plugin-commonjs，在能在rollup中使用
import parseHeaders from "parse-headers";
import AxionsInterceptors, { Interceptors } from "./AxionsInterceptors";
class Axios {
  //给axios实例增加 interceptors
  public interceptors = {
    request: new AxionsInterceptors<InternalAxiosRequestConfig>(),
    response: new AxionsInterceptors<AxiosResponse>(),
  };
  //axios 核心请求方法
  request<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    console.log(this.interceptors);
    //构建拦截器链路
    const chain: (
      | Interceptors<InternalAxiosRequestConfig>
      | Interceptors<AxiosResponse>
    )[] = [{ onFufilled: this.dispatchRequest }] as any;
    this.interceptors.request.interceptors.forEach((interceptor) => {
      interceptor && chain.unshift(interceptor);
    });
    this.interceptors.response.interceptors.forEach((interceptor) => {
      interceptor && chain.push(interceptor);
    });
    let promise: Promise<AxiosRequestConfig | AxiosResponse> =
      Promise.resolve(config);
    while (chain.length - 1) {
      const { onFufilled, onReject } = chain.shift()!;
      promise = promise.then(//这里取出来的可能是请求拦截器，也有可能是响应拦截器
        onFufilled as (v: AxiosRequestConfig | AxiosResponse) => any,
        onReject
      );
    }
    //发送请求之前，我们需要进行一些操作，比如：合并、修改等
    //1、对配置进行合并，默认值
    //2、拦截器
    //3、发送真正请求
    return promise as Promise<AxiosResponse<T>>;
  }
  dispatchRequest<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return new Promise((resolve, reject) => {
      let { url, method, params, headers, data, timeout } = config;
      console.log(1100,config);
      
      //3.1创建一个ajax对象
      const request = new XMLHttpRequest();
      //params事路径需要放到url里面
      //  @types/qs 可以把params解析为name=a&age=12
      if (params) {
        if (typeof params === "object") {
          params = qs.stringify(params);
        }
        // /path?name=a&age=12
        url += url?.includes("?") ? "&" : "?" + params;
      }
      request.open(method!, url!, true);
      if (headers) {
        for (const key in headers) {
          request.setRequestHeader(key, headers[key]);
        }
      }
      request.responseType = "json";

      request.onreadystatechange = () => {
        //  请求发送成功了，status=0表示请求未发送，请求（网络）异常
        if (request.readyState === 4 && request.status !== 0) {
          //请求成功，而且状态码是2XX
          if (request.status >= 200 && request.status < 300) {
            //返回请求的数据
            //parse-headers 解析返回的header，字符串转化为对象
            let response: AxiosResponse<T> = {
              data: request.response || request.responseText,
              status: request.status,
              statusText: request.statusText,
              headers: parseHeaders(request.getAllResponseHeaders()),
              config,
              request,
            };
            resolve(response);
          } else {
            reject(`my-Request failed with status code ${request.status}`);
          }
        }
      };
      //post请求参数处理
      let requestBody: null | string = null;
      if (data) {
        requestBody = JSON.stringify(data);
      }
      request.onerror = () => {
        reject("my-timeout of 1000ms exceeded");
      };
      console.log(11,config);
      
      if(config.cancelToken){
        console.log(66);
        
        config.cancelToken.then(message=>{
          request.abort()//取消请求
          reject(message)
        })
      }
      if (timeout) {
        request.timeout = timeout;
        request.ontimeout = () => {
          reject("my-net::ERR_INTERNET_DISCONNECTED");
        };
      }
      //发送请求
      request.send(requestBody);
    });
  }
}

export { Axios };
